package com.ruoyi.business.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.business.vo.*;
import com.ruoyi.common.utils.StringUtils;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.io.File;
import java.io.FileInputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.*;

@Service("HikVisionService")
public class HikVisionServiceImpl {

    private RestTemplate restTemplate;

    private static final Logger log = LoggerFactory.getLogger(HikVisionServiceImpl.class);


    public HikVisionServiceImpl() {
        //摘要认证时使用
        CredentialsProvider credsProvider = new BasicCredentialsProvider();
        credsProvider.setCredentials(new AuthScope(HikVisionApiConstants.HOST_WITHOUT_PROTOCOL, HikVisionApiConstants.PORT,
                        HikVisionApiConstants.REALM, AuthScope.ANY_SCHEME),
                new UsernamePasswordCredentials(HikVisionApiConstants.USERNAME, HikVisionApiConstants.PASSWORD));
        CloseableHttpClient httpclient = HttpClients.custom().setDefaultCredentialsProvider(credsProvider).build();

        RestTemplate restTemplate = new RestTemplate(new HttpComponentsClientHttpRequestFactory(httpclient));
        //支持中文编码
        restTemplate.getMessageConverters().set(1,
                new StringHttpMessageConverter(Charset.forName("UTF-8")));
        this.restTemplate = restTemplate;
    }




    public SearchResult getDeviceList() throws Exception {
        Filter filter = new Filter("", "AccessControl", Arrays.asList("ehomeV5"), Arrays.asList("online", "offline"));
        SearchDescription searchDescription = new SearchDescription(0, 1000, filter);
        HashMap<String, Object> map = new HashMap<>();
        map.put("SearchDescription", searchDescription);
        String jsonData = JSON.toJSONString(map);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<String> request = new HttpEntity<>(jsonData, headers);
        ResponseEntity<JSONObject> entity = restTemplate.postForEntity(HikVisionApiConstants.DEVICE_LIST, request, JSONObject.class);
        HttpStatus statusCode = entity.getStatusCode();
        if (statusCode != HttpStatus.OK) {
            throw new Exception(entity.getStatusCode().toString());
        }
        JSONObject body = entity.getBody();
        String searchResult = JSON.toJSONString(body.get("SearchResult"));
        SearchResult result = null;
        if (StringUtils.isNotEmpty(searchResult)) {
            result = JSONObject.parseObject(searchResult, SearchResult.class);
        }
        return result;
    }

    public DeviceInfoOutList addDevice(HikDeviceInfo hikDeviceInfo) throws Exception {
        List<HashMap<String, HikDeviceInfo>> deviceInfos = new ArrayList<>();
        deviceInfos.add(new HashMap<String, HikDeviceInfo>() {{
            put("Device",hikDeviceInfo);
        }});
        Map<String, List<HashMap<String, HikDeviceInfo>>> map = new HashMap<>();
        map.put("DeviceInList", deviceInfos);
        String jsonString = JSON.toJSONString(map);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<String> request = new HttpEntity<>(jsonString, headers);
        ResponseEntity<JSONObject> entity = restTemplate.postForEntity(HikVisionApiConstants.ADD_DEVICE, request, JSONObject.class);
        HttpStatus statusCode = entity.getStatusCode();
        if (statusCode != HttpStatus.OK) {
            throw new Exception(entity.getStatusCode().toString());
        }
        JSONObject body = entity.getBody();
        String result = JSON.toJSONString(body.get("DeviceOutList"));
        DeviceInfoOutList deviceInfoOutList = null;
        if (StringUtils.isNotEmpty(result)) {
            deviceInfoOutList = JSONObject.parseObject(JSON.toJSONString(body), DeviceInfoOutList.class);
        }
        return deviceInfoOutList;
    }

    public Boolean deleteDevice(String devIndex) throws Exception {
        HashMap<String, ArrayList<String>> map = new HashMap<>();
        ArrayList<String> strings = new ArrayList<>();
        strings.add(devIndex);
        map.put("DevIndexList", strings);
        String jsonString = JSON.toJSONString(map);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<String> request = new HttpEntity<>(jsonString, headers);
        ResponseEntity<JSONObject> entity = restTemplate.postForEntity(HikVisionApiConstants.DELETE_DEVICE, request, JSONObject.class);
        HttpStatus statusCode = entity.getStatusCode();
        if (statusCode != HttpStatus.OK) {
            throw new Exception(entity.getStatusCode().toString());
        }
        JSONObject body = entity.getBody();
        String result = JSON.toJSONString(body.get("DelDevList"));
        if (StringUtils.isNotEmpty(result)) {
            ArrayList<LinkedHashMap> list = (ArrayList<LinkedHashMap>) body.get("DelDevList");
            if (list.size() > 0) {
                LinkedHashMap jsonObject = list.get(0);
                LinkedHashMap dev = (LinkedHashMap) jsonObject.get("Dev");
                if (dev != null && ((String)dev.get("status")).equals("success")) {
                    return true;
                }
            }
        }
        return false;
    }

    public UserInfoOutList addPerson(List<UserInfo> userInfos, String deviceUuid) throws Exception {
        HashMap<String, Object> map = new HashMap<>();
        map.put("UserInfo", userInfos);
        String jsonData = JSON.toJSONString(map);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<String> request = new HttpEntity<>(jsonData, headers);
        ResponseEntity<JSONObject> entity = restTemplate.postForEntity(String.format(HikVisionApiConstants.ADD_PERSON, deviceUuid), request, JSONObject.class);
        HttpStatus statusCode = entity.getStatusCode();
        if (statusCode != HttpStatus.OK) {
            throw new Exception(entity.getStatusCode().toString());
        }
        JSONObject body = entity.getBody();
        String searchResult = JSON.toJSONString(body.get("UserInfoOutList"));
        UserInfoOutList result = null;
        if (StringUtils.isNotEmpty(searchResult)) {
            result = JSONObject.parseObject(searchResult, UserInfoOutList.class);
        }
        return result;
    }

    public ResponseStatus deletePerson(List<UserInfo> userInfos, String deviceUuid) throws Exception {
        HashMap<String, Object> map = new HashMap<>();
        List<Map> list = new ArrayList<>();
        userInfos.forEach(userInfo -> {
            list.add(new HashMap<String, String>() {
                {
                    put("employeeNo", userInfo.getEmployeeNo());
                }
            });
        });
        UserInfoDetail userInfoDetail = new UserInfoDetail("byEmployeeNo", list);
        map.put("UserInfoDetail", userInfoDetail);
        String jsonData = JSON.toJSONString(map);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<String> request = new HttpEntity<>(jsonData, headers);
        ResponseEntity<ResponseStatus> entity = restTemplate.exchange(String.format(HikVisionApiConstants.DELETE_PERSON, deviceUuid),
                HttpMethod.PUT, request, ResponseStatus.class);
        HttpStatus statusCode = entity.getStatusCode();
        if (statusCode != HttpStatus.OK) {
            throw new Exception(entity.getStatusCode().toString());
        }
        return entity.getBody();
    }

    public ResponseStatus addFace(FaceInfo faceInfo, String deviceUuid, String filePath) throws Exception {
        HashMap<String, Object> map = new HashMap<>();
        map.put("FaceInfo", faceInfo);

        MultiValueMap<String, Object> formDataMap = new LinkedMultiValueMap<>();
        formDataMap.add("FaceDataRecord", map);

        File file = new File(filePath);
        FileInputStream fileInputStream = new FileInputStream(file);
        CommonInputStreamResource commonInputStreamResource = null;
        try {
            commonInputStreamResource = new CommonInputStreamResource(fileInputStream,file.length(),file.getName());
        } catch (Exception e) {
            System.out.println("文件输入流转换错误" + e.toString());
        }

        formDataMap.add("FaceImage", commonInputStreamResource);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);
        HttpEntity<MultiValueMap> request = new HttpEntity<>(formDataMap , headers);

        ResponseStatus responseStatus = new ResponseStatus();
        responseStatus.setStatusCode(0);

        try {
            ResponseEntity<ResponseStatus> entity = restTemplate.postForEntity(String.format(HikVisionApiConstants.ADD_FACE,
                    deviceUuid), request, ResponseStatus.class);
            HttpStatus statusCode = entity.getStatusCode();
            if (statusCode != HttpStatus.OK) {
                throw new Exception(entity.getStatusCode().toString());
            }
            return entity.getBody();
        } catch (Exception e) {
            log.info(JSONObject.toJSONString(e));
            if (e.getMessage().contains("deviceUserAlreadyExistFace")) {
                responseStatus.setStatusCode(1);
            }
        }
        return responseStatus;
    }

    public ResponseStatus deleteFace(List<UserInfo> userInfos, String deviceUuid) throws Exception {
        HashMap<String, Object> map = new HashMap<>();
        map.put("EmployeeNoList", userInfos);

        HashMap<String, Object> smap = new HashMap<>();
        smap.put("FaceInfoDelCond", map);

        HttpHeaders headers = new HttpHeaders();
        HttpEntity request = new HttpEntity<>(smap , headers);

        ResponseEntity<ResponseStatus> entity = restTemplate.postForEntity(String.format(HikVisionApiConstants.DELETE_FACE, deviceUuid), request, ResponseStatus.class);
        HttpStatus statusCode = entity.getStatusCode();
        if (statusCode != HttpStatus.OK) {
            throw new Exception(entity.getStatusCode().toString());
        }
        return entity.getBody();
    }

    public ResponseStatus doorControl(String cmd, String acGatewayIndex, String deviceUuid) throws Exception {
        HashMap<String, Object> map = new HashMap<>();
        map.put("cmd", cmd);

        HashMap<String, Object> smap = new HashMap<>();
        smap.put("RemoteControlDoor", map);

        HttpHeaders headers = new HttpHeaders();
        HttpEntity request = new HttpEntity<>(smap , headers);

        ResponseEntity<ResponseStatus> entity = restTemplate.exchange(String.format(HikVisionApiConstants.DOOR_CONTROL, acGatewayIndex, deviceUuid),
                HttpMethod.PUT, request, ResponseStatus.class);
        HttpStatus statusCode = entity.getStatusCode();
        if (statusCode != HttpStatus.OK) {
            throw new Exception(entity.getStatusCode().toString());
        }
        return entity.getBody();
    }

}
